from pydantic import BaseModel, Field, HttpUrl, EmailStr, UUID1
from typing import Literal, List, Annotated, Optional, Union
from fastapi import APIRouter, Response, status, HTTPException, Form, File, UploadFile, Depends, Header
from fastapi.responses import HTMLResponse

import uvicorn

res_app = APIRouter()

@res_app.post("/response/", status_code=status.HTTP_201_CREATED)
def response_d():
    return {"message": "Response 模型"}


items = {
    "foo": {"name": "Foo", "price": 50.2},
    "bar": {"name": "Bar", "description": "The bartenders", "price": 62, "tax": 20.2},
    "baz": {"name": "Baz", "description": None, "price": 50.2, "tax": 10.5, "tags": []},
}

@res_app.get("/items/{item_id}")
async def read_item(item_id: str, response: Response):
    response.headers["X-Custom-Header"] = "Hello world"
    if item_id not in items:
        raise HTTPException(
            status_code=404,
            detail="Item not found",
        )
    return {"item": items[item_id]}

@res_app.post("/login/")
async def login(username: str = Form(), password: str = Form()):
    return {"username": username}

# 上传文件
"""使用File类 文件内容会以bytes的形式读入内存 适合于上传小文件"""
@res_app.post("/file/")
async def create_file(file: bytes = File()):
    return {"file_size": len(file)}

# 上传大文件
@res_app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
    """
        使用UploadFile类的优势:
        1.文件存储在内存中，使用的内存达到阈值后，将被保存在磁盘中
        2.适合于图片、视频大文件
        3.可以获取上传的文件的元数据，如文件名，创建时间等
        4.有文件对象的异步接口
        5.上传的文件是Python文件对象，可以使用write(), read(), seek(), close()操作
    """
    return {"filename": file.filename, "content_type": file.content_type}


@res_app.post("/files/")
async def create_files(files: list[bytes] = File()):
    return {"file_sizes": [len(file) for file in files]}


@res_app.post("/uploadfiles/")
async def create_upload_files(files: list[UploadFile]):
    return {"filenames": [file.filename for file in files]}


@res_app.get("/")
async def main():
    content = """
<body>
<form action="/resp/files/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
<form action="/resp/uploadfiles/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
</body>
    """
    return HTMLResponse(content=content)



async def common_parameters(q: str = None, skip: int = 0, limit: int = 100):
    return {"q": q, "skip": skip, "limit": limit}

@res_app.get("/items/depend/")
async def read_items(commons: dict = Depends(common_parameters)):
    return commons

@res_app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):
    return commons



# 把一个类做为依赖项
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}, {"item_name": "Baz"}, {"item_name": "Baz"}]


class CommonQueryParams:
    def __init__(self, q: str | None = None, skip: int = 0, limit: int = 100):
        self.q = q
        self.skip = skip
        self.limit = limit


@res_app.get("/items/depends_class/")
async def read_items(commons:CommonQueryParams = Depends(CommonQueryParams)):
    response = {}
    if commons.q:
        response.update({"q": commons.q})
    items = fake_items_db[commons.skip : commons.skip + commons.limit]
    response.update({"items": items})
    return response


# 在路径操作中增加多个依赖项
async def verify_token(x_token: Annotated[str, Header()]):
    if x_token != "fake-super-secret-token":
        raise HTTPException(status_code=400, detail="X-Token header invalid")


async def verify_key(x_key: Annotated[str, Header()]):

    if x_key != "fake-super-secret-key":
        raise HTTPException(status_code=400, detail="X-Key header invalid")
    return x_key


@res_app.get("/items/abc/", dependencies=[Depends(verify_token), Depends(verify_key)])
async def read_items():
    return [{"item": "Foo"}, {"item": "Bar"}]